//
//  VPOSLocationManager.m
//  ShowMaps
//
//  Created by handpay on 12-12-4.
//  Copyright (c) 2012年 lihui. All rights reserved.
//

#import "VPOSLocationManager.h"
#import "HPClientEngine.h"

#define kDefaultTimeoutInterval     10

static VPOSLocationManager *vposLM = nil;

@interface VPOSLocationManager()
{
    VPOSLocateSuccessBlock successBlock;
    VPOSLocateFailBlock failBlock;
    VPOSAddressSuccessBlock addressSuccessBlock;
    NSTimer *timeoutTimer;
}
@property(nonatomic, retain)CLLocationManager *locationManager;
@property(nonatomic, assign) BOOL locationFlag;

@end

@implementation VPOSLocationManager

+ (VPOSLocationManager *)sharedInstance
{
    if (!vposLM)
    {
        vposLM = [[super allocWithZone:NULL] init];
    }
    return vposLM;
}

+ (id)allocWithZone:(struct _NSZone *)zone
{
    return [self sharedInstance];
}

- (void)stopTimer{
    if (timeoutTimer) {
        if (timeoutTimer.isValid) {
            [timeoutTimer invalidate];
        }
        [timeoutTimer release];
        timeoutTimer = nil;
    }
}

- (void)dealloc
{
    [self stopTimer];
    self.locationManager = nil;
    if (successBlock) {
        [successBlock release];
        successBlock = nil;
    }
    if (failBlock) {
        [failBlock release];
        failBlock = nil;
    }
    if (addressSuccessBlock) {
        [addressSuccessBlock release];
        addressSuccessBlock = nil;
    }
    
    [super dealloc];
}

- (id) init
{
    self = [super init];
    if (self) {
        [self clearData];
    }
    return self;
}

- (void)clearData
{
    self.locationManager = nil;
    successBlock = nil;
    failBlock = nil;
    addressSuccessBlock = nil;
    self.locationFlag = NO;
}

- (void) timeout
{
    [self stopTimer];
    if (failBlock) {
        failBlock([NSError errorWithDomain:@"LocateTimeout" code:-1 userInfo:nil]);
    }
//    CLLocation * location = [[CLLocation alloc]initWithLatitude:0 longitude:0];
//    [self returnResultCoordinate:location error:[NSError errorWithDomain:@"LocateTimeout" code:-1 userInfo:nil] fromTimeout:YES];
//    [location release];
}

- (void) locateSuccess:(void (^)(CLLocationCoordinate2D userLocationCoordinate))success Fail:(void (^)(NSError *error))fail timeoutInterval:(NSTimeInterval)timeoutInterval{
    [self clearData];
    
    timeoutInterval = [self setNormalValue:fail timeoutInterval:timeoutInterval];
    
    if (successBlock) {
        [successBlock release];
        successBlock = nil;
    }
    
    if (success) {
        successBlock = [success copy];
    }
    
    [self checkLocAction:timeoutInterval];
}

- (void)checkLocAction:(NSTimeInterval)timeoutInterval{
    CLAuthorizationStatus locStatus =  [CLLocationManager authorizationStatus];
    if (locStatus == kCLAuthorizationStatusNotDetermined) {
        [self performSelectorOnMainThread:@selector(initLocManagerOnMainThread:) withObject:[NSNumber numberWithDouble:timeoutInterval] waitUntilDone:NO];
        return;
    }
    
    BOOL locEnabled = [CLLocationManager locationServicesEnabled];
    if (locEnabled && locStatus == kCLAuthorizationStatusAuthorized) {
        [self performSelectorOnMainThread:@selector(initLocManagerOnMainThread:) withObject:[NSNumber numberWithDouble:timeoutInterval] waitUntilDone:NO];
        return;
    }
    
    NSError* error = [NSError errorWithDomain:@"handpay not allow" code:-1 userInfo:nil];
    if (failBlock) {
        failBlock(error);
    }
    
}

- (NSTimeInterval)setNormalValue:(void (^)(NSError *))fail timeoutInterval:(NSTimeInterval)timeoutInterval{
    if (timeoutInterval <= 0) {
        timeoutInterval = kDefaultTimeoutInterval;
    }
    
    if (failBlock) {
        [failBlock release];
        failBlock = nil;
    }
    
    if (fail) {
        failBlock = [fail copy];
    }
    
    return timeoutInterval;
}

- (void) locateSuccessWithAddress:(void (^)(CLLocationCoordinate2D, NSDictionary *))success Fail:(void (^)(NSError *))fail timeoutInterval:(NSTimeInterval)timeoutInterval
{
    [self clearData];
    timeoutInterval = [self setNormalValue:fail timeoutInterval:timeoutInterval];
    
    if (addressSuccessBlock) {
        [addressSuccessBlock release];
        addressSuccessBlock = nil;
    }
    
    if (success) {
        addressSuccessBlock = [success copy];
    }
    
    [self checkLocAction:timeoutInterval];

}
- (void) initLocManagerOnMainThread:(NSNumber*)timeoutInterval
{
    if (self.locationManager == nil) {
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
        
        [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
        self.locationManager.distanceFilter = 1000.0f;
    }
    
    if (!timeoutTimer) {
        timeoutTimer = [[NSTimer scheduledTimerWithTimeInterval:[timeoutInterval doubleValue] target:self selector:@selector(timeout) userInfo:nil repeats:NO] retain];
    }
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        [self.locationManager requestAlwaysAuthorization];
    }
    [self.locationManager startUpdatingLocation];
    
}

#pragma mark - locationManager delegate
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    switch (status) {
            
        case kCLAuthorizationStatusNotDetermined:
            if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
                
                [self.locationManager requestWhenInUseAuthorization];
                
            }
            break;
        default:
            break;
    }
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    if (failBlock) {
        [self returnResultCoordinate:nil error:error fromTimeout:NO];
    }
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
    if (!self.locationFlag) {
        //停止定位操作
        [self.locationManager stopUpdatingLocation];
        if (successBlock || addressSuccessBlock) {
            self.locationFlag = YES;
            [self returnResultCoordinate:newLocation error:nil fromTimeout:NO];
        }
    }
}

- (void) returnResultAddress:(CLLocationCoordinate2D)coordinate placemark:(CLPlacemark *)placemark error:(NSError *)error{
    @synchronized(self) {
        NSString *addr = @"";
        NSMutableDictionary * dic = [[NSMutableDictionary alloc]initWithCapacity:4];
        if (placemark != nil) {
            NSArray * addressArray = [placemark.addressDictionary objectForKey:@"FormattedAddressLines"];
            
            if (addressArray && addressArray.count > 0) {
                addr = [addressArray objectAtIndex:0];
            }
            
            
            NSString *state =[placemark.addressDictionary objectForKey:KStateKey];
            NSString *city = placemark.locality;
            if ([NSString isNilOrEmpty:city] && state) {
                city = state;
            }
            
            if ([NSString isNilOrEmpty:state] && city) {
                state = city;
            }
            
            if (!state) {
                state = @"";
            }
            
            if (!city) {
                city = @"";
            }
           
            NSString *subLocality = [placemark.addressDictionary objectForKey:KSubLocalityKey];
            
            if ([NSString isNilOrEmpty:subLocality]) {
                subLocality = @"";
            }
            [dic setObject:state forKey:KStateKey];
            [dic setObject:city forKey:KCityKey];
            [dic setObject:subLocality forKey:KSubLocalityKey];
            [dic setObject:addr forKey:KAddressKey];
        }
        if (error && failBlock) {
            failBlock(error);
        }else if(addressSuccessBlock){
            addressSuccessBlock(coordinate,dic);
        }
        [dic release];
    }
}

- (void) returnResultCoordinate:(CLLocation *)location error:(NSError *)error fromTimeout:(BOOL)fromTimeout
{
    @synchronized(self) {
        if (!fromTimeout) {
            [self stopTimer];
        }
        if (error && failBlock) {
            failBlock(error);
        }else {
            
            if (!fromTimeout && successBlock) {
                successBlock(location.coordinate);
            }
            if (addressSuccessBlock) {
                CLGeocoder *geocoder = [[CLGeocoder alloc] init];
                
//ZZT_FOR_ADDRESS
                NSString* longtitude = [HPCLIENTENG GetGlobalData:@"longtitude"];
                NSString* Latitude = [HPCLIENTENG GetGlobalData:@"Latitude"];
                if (![NSString isNilOrEmpty:longtitude]) {
                    location = [[[CLLocation alloc]initWithLatitude:Latitude.doubleValue longitude:longtitude.doubleValue]autorelease];
                }
                
//
                [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *array, NSError *error) {
                    if (array.count > 0) {
                        
                        CLPlacemark *placemark = [array objectAtIndex:0];
                        
                        [self returnResultAddress:location.coordinate placemark:placemark error:nil];
                    }else{
                        failBlock(error);
                    }
                }];
                [geocoder autorelease]; // mcm new : fix memery leak
            }
        }
    }
}

@end
